<?php
namespace Api\Controller;

use app\index\controller\Wxauth;
use Common\Model\Log\LogModel;
use Common\Util\BaseData;
use Common\Util\UserData;
use Common\Util\WechatAuth;
use Common\Util\WechatUtil;
use Services\Fenxiao\FenxiaoService;
use Services\Log\LogService;
use think\Cache;
use think\Controller;
use think\Db;

class AuthController extends BaseController {

    const SUCCESS_CODE = 1;
    const ERROR_CODE = 0;

	protected $this_controller;

	protected $this_action;

	protected $this_app_config;

	protected function _initialize(){
		header("Access-Control-Allow-Origin:*");
		$this->utoken = $this->getUtoken();
		$this_action = CONTROLLER_NAME.'/'.ACTION_NAME;
		$this->this_controller = CONTROLLER_NAME;
		$this->this_action = $this_action;
		$this->assign('this_controller', $this->this_controller);
		$this->assign('this_url_action', __ACTION__);
		$this->this_app_config = BaseData::getAppSetting();
		$this->assign('app_config', $this->this_app_config);
	}

    /**
     * 拿到用户登录令牌
     * @return mixed|string
     */
    private function getUtoken(){
        $token = arr_get($_SERVER,'HTTP_TOKEN');
        if(!$token){
            $token = $_GET['token']??'';
        }
        if(!$token){
            $token = $_POST['token']??'';
        }
        return $token;
    }
	const GET_ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/sns/oauth2/access_token'; // 获取access_token url

	const GET_USER_INFO_URL = 'https://api.weixin.qq.com/sns/userinfo';               // 获取用户信息url

	const GET_CODE = 'https://open.weixin.qq.com/connect/oauth2/authorize';// 获取code(网页授权使用)

	/**
	 * 用户同意授权获取code
	 *
	 * @param string $redirect_uri 授权后重定向的回调链接地址，需要urlEncode处理
	 * @return
	 */
	public function getCode(){
		$app_system_setting = BaseData::getAppSetting();
		$redirect_uri = $app_system_setting['app_domain'].'/h5app';
		$redirect_uri = $_GET['redirect_uri'] ? $_GET['redirect_uri'] : $redirect_uri;
		$appid = $app_system_setting['wechat_appid'];
		$uri = $this->combineURL(self::GET_CODE, [
			'appid'         => $appid,
			'scope'         => 'snsapi_userinfo',
			'response_type' => 'code',
			'redirect_uri'  => urlEncode($redirect_uri),
		]);
		$this->return_app_data(1, $uri);
	}

	public function callblock(){
        try {
            $data = $_GET;
            $code = $data['code'];
            if ($code) {
                $user_info = $this->wxLogin($code);
                (new LogModel())->addLog('auth_callback', $user_info);
                if (!$user_info) {
                    $this->return_app_data(0, '此页面已失效');
                }
                $users = $user_info;
                $openid = $user_info['openid'];
            }
            $user = M('user')->where("user_openid='{$openid}'")->find();
            $token = md5(uniqid());
            //todo：处理用户头像上传,压入子记录头像进行异步更新

            $userData = [
                'user_openid' => $users['openid'],
                'user_nickname' => $users['nickname'],
                'user_headimg' => $users['headimgurl'],
                'token' => $token,
                'star' => 0,
                'add_time' => time(),
                'update_time' => time(),
            ];
            if (!$user) {
                //新用户的话直接新增
                $insertId = M('user')->add($userData);
                //进行分销用户的绑定
                (new FenxiaoService())->setParams([
                    'user_id' => $insertId,
                    'parent_user_id' => arr_get($data,'parent_user_id','')
                ])->bind();
                if ($insertId) {
                    $id = M('user')->getLastInsID();
                    S($token, $id, 3600 * 24 * 7);
                    $this->return_app_data(1, $token);
                } else {
                    $this->return_app_data(0, '添加失败');
                }
            } else {
                M("user")->where("id={$user['id']}")->save([
                    'user_nickname' => $users['nickname'],
                    'user_headimg' => $users['headimgurl'],
                    'update_time' => time(),
                ]);
                S($user['token'], $user['id'], 3600 * 24 * 7);
                $this->return_app_data(1, $user['token']);
            }
        } catch (\Exception $e) {
            (new LogModel())->addLog('auth_callback_error', ['msg' => $e->getMessage(),'trace' => array_slice($e->getTrace(), 0, 5)]);
        }
    }

	public function wxLogin($code){
		$token_info = $this->getToken($code);
		if(isset($token_info['errcode'])){
			$this->error = $token_info;
			return false;
		}
		$user_info = $this->getUserinfo($token_info['openid'], $token_info['access_token']);
		if(isset($user_info['errcode'])){
			$this->error = $user_info;
			return false;
		}
		return $user_info;
	}

	/**
	 * 获取用户信息
	 *
	 * @param string $openid 用户的标识
	 * @param string $access_token 调用接口凭证
	 * @return array 用户信息
	 */
	public function getUserinfo($openid, $access_token){
		$get_userinfo_url = $this->combineURL(self::GET_USER_INFO_URL, [
			'openid'       => $openid,
			'access_token' => $access_token,
			'lang'         => 'zh_CN',
		]);
		$user_info = $this->httpsRequest($get_userinfo_url);
		return json_decode($user_info, true);
	}

	/**
	 * 获取token和openid
	 *
	 * @param string $code 客户端传回的code
	 * @return array 获取到的数据
	 */
	public function getToken($code){
		$app_system_setting = BaseData::getAppSetting();
		$appid = $app_system_setting['wechat_appid'];
		$wechat_appsecret = $app_system_setting['wechat_appsecret'];
        (new \Common\Model\Log\LogModel())->addLog(__FUNCTION__,['appid' => $appid,'secret' => $wechat_appsecret]);
		$get_token_url = $this->combineURL(self::GET_ACCESS_TOKEN_URL, [
			'appid'      => $appid,
			'secret'     => $wechat_appsecret,
			'code'       => $code,
			'grant_type' => 'authorization_code',
		]);
		$token_info = $this->httpsRequest($get_token_url);
		return json_decode($token_info, true);
	}

	/**
	 * 拼接url
	 *
	 * @param string $baseURL 请求的url
	 * @param array  $keysArr 参数列表数组
	 * @return string           返回拼接的url
	 */
	public function combineURL($baseURL, $keysArr){
		$combined = $baseURL."?";
		$valueArr = [];
		foreach($keysArr as $key => $val){
			$valueArr[] = "$key=$val";
		}
		$keyStr = implode("&", $valueArr);
		$combined .= ($keyStr);
		return $combined;
	}

	/**
	 * 获取服务器数据
	 *
	 * @param string $url 请求的url
	 * @return  unknown    请求返回的内容
	 */
	public function httpsRequest($url){
		$curl = curl_init();
		curl_setopt($curl, CURLOPT_URL, $url);
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
		$output = curl_exec($curl);
		curl_close($curl);
		return $output;
	}

	public function checkUserUtoken(){
		$utoken = $this->utoken;
		$get_user_info = BaseData::getUserInfoByToken($utoken);
		if($get_user_info == false){
			S($utoken, null);
			$this->return_app_data(-1, '对不起，登录超时');
		}
		//		if($get_user_info['user_login_status'] == 2){
		//			$this->return_app_data(-1, '帐户被锁定，请联系客服处理');
		//		}

		return $get_user_info;
	}


    /**
     * 用户是否已经授权
     * @return bool
     */
    public function userIsAuth(){
        $utoken = $this->utoken;
        $userInfo = BaseData::getUserInfoByToken($utoken);
        return !empty($userInfo);
    }

    /**
     * 获取用户的id
     * @return mixed|string
     */
    public function getUserId(){
        $userInfo = $this->checkUserUtoken();
        return arr_get($userInfo,'id');
    }

	/**
	 * 页面提示跳转
	 *
	 * @param string $type
	 * @param string $message
	 * @param string $url
	 */
	public function jumpTipsPage($type = 'success', $message = '', $button = ''){
		$info = ['type' => $type, 'message' => $message];
		$this->assign('info', $info);
		$this->assign('button', $button);
		$this->display('Common/tips_page');
		exit();
	}

	/**
	 * 获取jssdk
	 *
	 * @return array
	 */
	public function getJssdkData($jssdk_url){
		//生成微信JSSDK参数
		$wechat_jsapi_ticket = WechatAuth::getJsapiTicket();
		$jssdk_noncestr = md5(time().rand(111, 999));
		$jssdk_timestamp = time();
		$jssdk_str = "jsapi_ticket=".$wechat_jsapi_ticket."&noncestr=".$jssdk_noncestr."&timestamp=".$jssdk_timestamp."&url=".$jssdk_url;
		$jssdk_signature = sha1($jssdk_str);
		$jssdk_param_data = [
			'appId'     => $this->this_app_config['wechat_appid'],
			'timestamp' => $jssdk_timestamp,
			'nonceStr'  => $jssdk_noncestr,
			'signature' => $jssdk_signature,
		];
		return $jssdk_param_data;
	}

	/**
	 * 上传微信图片
	 */
	public function uploadWxImg(){
		$mediaId = $_POST['mediaId'] ? trim($_POST['mediaId']) : '';
		$wechat_access_token = WechatAuth::getAccessToken();
		$url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=".$wechat_access_token."&media_id=".$mediaId;
		$img_con = cyz_curl_get_contents($url);
		if($img_con['errcode'] == '40007'){
			$this->return_app_data(0, '上传失败，请重试');
		}else{
			$file_name = 'SIMG_'.date("YmdHis").mt_rand(1, 9999).mt_rand(1, 9999);
			$url = BaseData::uploadStaticFile($file_name, $img_con, true);
			$this->return_app_data(1, $url);
		}
	}

	/**
	 * 过滤用户输入数据
	 *
	 * @param $str
	 * @return mixed|string
	 */
	public function formatFormText($str){
		$str = cyz_compile_str($str);
		$str = cyz_make_semiangle($str);
		$str = preg_replace('# #', '', $str);//清除所有空格
		return $str;
	}

	//	根据两个地点的经纬度计算距离
	public function getDistance($lat1, $lng1, $lat2, $lng2){
		$earthRadius = 6371000;
		$lat1 = ($lat1 * pi()) / 180;
		$lng1 = ($lng1 * pi()) / 180;
		$lat2 = ($lat2 * pi()) / 180;
		$lng2 = ($lng2 * pi()) / 180;
		$calcLongitude = $lng2 - $lng1;
		$calcLatitude = $lat2 - $lat1;
		$stepOne = pow(sin($calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude / 2), 2);
		$stepTwo = 2 * asin(min(1, sqrt($stepOne)));
		$calculatedDistance = $earthRadius * $stepTwo;
		return round($calculatedDistance / 1000, 1);
	}

	/**
	 * 计算某个经纬度的周围某段距离的正方形的四个点
	 * 地球半径，平均半径为6371km
	 *
	 * @param lng float 经度
	 * @param lat float 纬度
	 * @param distance float 该点所在圆的半径，该圆与此正方形内切，默认值为1千米
	 * @return array 正方形的四个点的经纬度坐标
	 */
	public function getAroundCoordinate($lng, $lat, $distance = 1){
		$dlng = 2 * asin(sin($distance / (2 * 6371)) / cos(deg2rad($lat)));
		$dlng = rad2deg($dlng);
		$dlat = $distance / 6371;
		$dlat = rad2deg($dlat);

		return [
			'left-top'     => ['lat' => $lat + $dlat, 'lng' => $lng - $dlng],
			'right-top'    => ['lat' => $lat + $dlat, 'lng' => $lng + $dlng],
			'left-bottom'  => ['lat' => $lat - $dlat, 'lng' => $lng - $dlng],
			'right-bottom' => ['lat' => $lat - $dlat, 'lng' => $lng + $dlng],
		];
	}

	//   读取站点
	public function siteDistance($lat, $lng){
		$t_site_list = M("site_list");
		//获取该用户所在的地区附近的4个点
		$start = $this->getAroundCoordinate($lng, $lat, $distance = 500);
		//纬度
		$where['lat'] = ['between', [$start['left-bottom']['lat'], $start['left-top']['lat']]];
		//经度
		$where['lng'] = ['between', [$start['left-bottom']['lng'], $start['right-bottom']['lng']]];
		$list = $t_site_list->where($where)->select();
		foreach($list as $key => $val){
			//			计算距离
			$list[$key]['gap'] = $this->getDistance($lat, $lng, $val['lat'], $val['lng']);
		}

		//根据字段gap对数组$list进行升序排列
		$gap = $this->array_column($list, 'gap');
		array_multisort($gap, SORT_ASC, $list);
		return $list;
	}

	public function array_column($arr2, $column_key){
		$data = [];
		foreach($arr2 as $key => $value){
			$data[] = $value[$column_key];
		}
		return $data;
	}

}
